Z06-04 专题-Cloudflare
[TOC]
基础概念
本章将深入解析 Cloudflare 开发生态的两大基石——Workers 与 Pages,并探讨边缘计算架构与传统云服务的核心区别。
Cloudflare Workers:边缘计算引擎
什么是 Workers
Cloudflare Workers 是一个边缘计算无服务器平台(Edge Computing Serverless Platform)。 与传统云服务不同,它允许开发者编写代码(JavaScript, TypeScript, Rust 等),并将这些代码部署到 Cloudflare 遍布全球 300 多个城市的服务器节点上。
- 运行机制: 当用户访问应用时,代码会在离用户物理距离最近的节点上运行,而不是在遥远的源服务器上运行。
- 核心优势: 这种架构消除了网络延迟,让应用获得物理极限级别的访问速度。
核心技术:V8 Isolates vs 容器
Workers 极速响应的秘密在于其底层技术架构。它不使用 AWS Lambda 等传统 Serverless 平台常见的容器(Container)或虚拟机,而是采用谷歌 Chrome 浏览器的 V8 Isolates 引擎技术。
技术架构对比:
| 特性 | 传统 Serverless (如 AWS Lambda) | Cloudflare Workers |
|---|---|---|
| 底层技术 | 容器 / 微型操作系统 | V8 Isolates (轻量级上下文) |
| 启动机制 | 需启动操作系统环境 | 在现有进程中创建上下文 |
| 形象比喻 | 专门启动一辆卡车来送一个披萨(启动慢、开销大) | 在同一辆已经发动的卡车上多放一个披萨盒(零启动时间) |
| 冷启动时间 | 数百毫秒甚至几秒 | 0ms 冷启动 (几毫秒内执行) |
Workers 的核心能力
Workers 处于用户和源服务器之间,可以胜任多种角色:
- Backendless (无后端): 配合 D1 (数据库)、KV (键值存储)、R2 (对象存储),构建完全运行在边缘的全栈应用,无需任何传统 Linux 服务器。
- 中间件/代理 (Middleware/Proxy): 修改请求/响应头(Auth Header)、重定向路由、进行 A/B 测试。
- 性能优化: 自定义缓存逻辑或根据设备动态调整图片尺寸。
代码示例
Workers 基于 Web 标准 Service Worker API 构建,开发者使用的是熟悉的 Fetch, Request, Response 对象。
一个最简单的拦截请求并返回 "Hello World" 的 Worker 如下:
export default {
async fetch(request, env, ctx) {
return new Response('Hello World')
}
}(注:基于笔记描述补充的标准 Hello World 示例)
Cloudflare Pages:全栈托管平台
什么是 Pages
如果说 Workers 是为了解决“后端逻辑”在边缘运行的问题,那么 Cloudflare Pages 就是为了解决“前端页面”在边缘托管和构建的问题。它主要对标 Vercel 和 Netlify,是托管 Vue、React 等前端项目的最佳方案。
核心工作流:自动化构建
Pages 改变了传统“本地打包 -> 手动上传 -> 配置 Nginx”的繁琐流程,实现了现代化的 GitOps 工作流:
- Git 集成: 连接 GitHub/GitLab 仓库。
- 自动构建: 云端监听到代码提交后,自动运行
npm install和npm build。 - 全球分发: 构建生成的静态文件(HTML/CSS/JS)自动分发到全球 300+ 节点。
- 预览环境 (Preview Deployments): 每个 Pull Request 都会自动部署一个临时的、独立的 URL(如
pr-123.project.pages.dev)供团队测试,合并后才会更新主环境。
Pages 与 Workers 的区别
- Workers:代码优先。 适合写 API、代理、复杂逻辑。虽然能返回 HTML,但不适合管理大量静态资源。
- Pages:文件/资产优先。 专为托管静态网站设计,擅长处理文件存储和分发。
Pages Functions (全栈能力)
这是 Pages 的“杀手锏”。通过在项目根目录创建 functions 文件夹,开发者可以在 Pages 项目中直接编写后端逻辑。
自动路由:
functions目录下的文件会自动部署为 Workers 并生成 API 路由。functions/api/login.js-> 自动映射为/api/login接口。
Monorepo 优势: 前端(Vue)与后端(Functions)在同一个仓库中管理,共享环境变量和 D1/KV 绑定,无需跨域配置(因为同属一个域名)。
架构选型建议
在迁移传统应用(如阿里云上的 Vue + Nginx)时,有两种架构模式可供选择:
架构 A:混合模式
- 前端: 托管在 Cloudflare Pages。
- 后端: 独立的 Cloudflare Workers 项目。
- 连接: 前端通过 HTTP 请求调用后端 URL。
- 特点: 前后端完全解耦,适合独立开发团队。
架构 B:全栈 Pages 模式 (推荐)
- 结构: 单个 GitHub 仓库 (Monorepo)。
- 前端: Vue/React 代码。
- 后端:
functions/目录下的 API 代码。 - 特点: 管理方便,共享资源绑定,无需维护两个项目,适合个人开发者和全栈应用。
核心计算
本章将深入剖析 Cloudflare 的计算运行时环境,从底层的 V8 隔离技术到上层的 Pages Functions 开发模式,帮助开发者理解为何它能实现“零冷启动”以及如何构建高效的全栈应用。
V8 引擎机制
Cloudflare Workers 的核心竞争力在于其独特的运行机制,这与 AWS Lambda 等传统 Serverless 方案有着本质区别。
V8 Isolates 技术原理
Workers 并不使用容器 (Container) 或虚拟机,而是采用了谷歌 Chrome 浏览器的 V8 Isolates 引擎技术。
传统 Serverless (如 AWS Lambda):
机制: 当请求到达时,云服务商需要启动一个微型操作系统环境(容器)。
代价: 这个过程会产生显著的**“冷启动”**时间,通常需要数百毫秒甚至几秒。
Cloudflare Workers:
机制: 它不启动新的操作系统,而是在现有的进程中创建一个轻量级的“上下文”(Isolate)。
优势: 实现了 0ms 冷启动,代码可以在几毫秒内开始执行。
形象比喻:披萨卡车
为了更好地理解这两种架构的区别,我们可以使用“披萨卡车”的比喻:
- 传统 Serverless: 就像为了送一个披萨,专门启动了一辆卡车。启动引擎很慢,且每送一单都要消耗整辆车的资源(开销大)。
- Workers: 就像在同一辆已经发动的卡车上多放了一个披萨盒。卡车本身已经在运行,放入披萨盒几乎不需要时间(零启动时间,开销极小)。
Pages 函数 (Pages Functions)
Cloudflare Pages 不仅支持静态文件托管,还通过 Pages Functions 提供了完整的后端能力,使其成为全栈开发的利器。
目录即路由
Pages 遵循“约定优于配置”的原则。在项目根目录下的 functions 文件夹里的代码,会自动部署为后端 API。
文件映射规则:
functions/api/login.js-> 自动映射为/api/login接口。functions/api/user.js-> 自动映射为/api/user接口。核心优势: 前端(Vue/React)和后端(Workers)代码放在同一个仓库里,Cloudflare 自动处理路由和构建,无需复杂的跨域配置。
实战代码:115 网盘通用接口
以下是一个真实的 Pages Function 示例,用于中转请求并欺骗 115 服务器。
文件路径: functions/api/115.js
export async function onRequest(context) {
// 从环境变量中获取 Cookie
const COOKIE = context.env.COOKIE_115
if (!COOKIE) {
return new Response(JSON.stringify({ state: false, error: '未配置 Cookie' }), {
headers: { 'Content-Type': 'application/json' }
})
}
// 获取前端传来的参数 (URL)
const url = new URL(context.request.url)
const targetUrl = url.searchParams.get('url') // 例如 ?url=https://webapi.115.com/...
if (!targetUrl) {
return new Response('Missing url param', { status: 400 })
}
// 发起请求给 115
// 注意:这里伪造了 User-Agent 和 Cookie
const resp = await fetch(targetUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
Cookie: COOKIE
}
})
// 把 115 的返回结果直接透传给前端
const data = await resp.json()
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' }
})
}API 解析:
onRequest(context): Pages Functions 的入口处理函数。context.env: 用于访问环境变量(如COOKIE_115)和绑定的资源(如 D1, KV)。context.request: 标准的 Web Request 对象,包含 URL、Headers 等信息。
实战代码:图片代理服务
针对 115 图片防盗链的处理,我们可以编写一个专门的图片代理 Function。
文件路径: functions/api/img-proxy.js
export async function onRequest(context) {
const COOKIE = context.env.COOKIE_115
const url = new URL(context.request.url)
const targetUrl = url.searchParams.get('url')
if (!targetUrl) return new Response('Missing URL', { status: 400 })
// 请求图片,带上 Cookie 和 Referer
const resp = await fetch(targetUrl, {
headers: {
Cookie: COOKIE,
Referer: 'https://115.com/' // 关键:骗过防盗链
}
})
// 直接返回图片流,不要 await resp.blob(),以节省内存
return new Response(resp.body, {
headers: {
'Content-Type': resp.headers.get('Content-Type') || 'image/jpeg'
}
})
}全栈开发模式
Cloudflare Pages 提供了两种主要的开发架构模式,开发者应根据项目需求进行选择。
架构对比
| 架构模式 | 描述 | 适用场景 |
|---|---|---|
| 架构 A:混合模式 | 前端在 Pages,后端是独立的 Workers 项目。前后端完全解耦,通过 HTTP 调用。 | 适合独立开发团队,或者后端逻辑极度复杂需要独立管理的场景。 |
| 架构 B:全栈 Pages 模式 (推荐) | Monorepo 结构。前端代码和 functions/ 目录下的 API 代码在同一个仓库。 | 管理方便,共享环境变量和 D1/KV 绑定,无需跨域配置。非常适合个人开发者构建全栈应用。 |
本地全栈开发环境配置
为了在本地模拟 Cloudflare 环境(同时运行 Vue 前端和 Functions 后端),我们需要利用 Wrangler 进行代理。
1. 配置本地环境变量 在项目根目录创建 .dev.vars 文件(注意:此文件不应提交到 Git):
COOKIE_115=UID=12345;CID=abcde;SEID=...2. 修改启动脚本 修改 package.json 的 scripts 字段,使用 Wrangler 来启动开发服务器:
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"pages:dev": "wrangler pages dev -- proxy 5173"
}3. 启动命令 运行 npm run pages:dev。
运行原理解析:
- Wrangler 启动并自动运行
npm run dev(Vite 服务器)。 - Wrangler 建立一个代理服务器(通常在
http://localhost:8788)。 - 请求拦截:
- 页面请求
/api/115-> Wrangler 拦截 -> 执行functions/api/115.js(读取.dev.vars中的变量)。 - 页面请求静态资源 -> Wrangler 转发给 Vite (端口 5173)。
通过这种方式,你可以在本地完整模拟线上的全栈运行环境,无需部署即可调试后端 API 和数据库逻辑。
数据存储
本章将详细介绍 Cloudflare 的三大核心存储解决方案:D1 (SQL 数据库)、KV (键值存储) 和 R2 (对象存储)。我们将从核心概念、适用场景、定价模式以及详细的 API 操作指南四个维度进行深入解析。
D1 数据库
什么是 D1
Cloudflare D1 是 Cloudflare 推出的原生无服务器(Serverless)关系型数据库。 简单来说,它是一个构建在 Cloudflare 全球网络边缘(Edge)上的 SQLite 数据库。
它的设计目标是为 Workers 应用提供一个低延迟、零配置、且支持标准 SQL 的数据存储方案。
核心特性
- 基于 SQLite: 并非 MySQL 或 PostgreSQL。这意味着你可以使用熟悉的 SQL 语法,且启动速度极快。
- 原生无服务器 (Serverless): 无需配置服务器或管理集群。通过 CLI 或控制台即可瞬间创建。
- 全球分布 (Global Distribution):
- 读操作: 支持全球读复制,自动在靠近用户的位置创建只读副本,实现极低延迟。
- 写操作: 发送到主实例(Primary),然后异步同步到其他副本。
- 深度集成: 通过绑定(Binding)机制,Worker 代码可以直接调用 D1,无需处理连接池或鉴权。
局限性与注意事项
- 单库容量限制: 目前单个数据库限制为 10 GB。
- 并发写入性能: 由于 SQLite 特性,单主节点模式在处理极高并发写入时性能不如传统数据库。
- 事务支持: 支持事务,但受限于分布式环境,复杂事务处理能力有限。
适用场景
- 边缘应用: 电商产品目录、内容管理系统。
- SaaS 多租户架构: 适合“一个租户一个数据库”的隔离模式。
- 高读低写: 针对“读多写少”场景优化。
定价模式
D1 不按实例时间计费,而是基于存储量和读写行数。
- 免费版: 每天 500 万行读取,10 万行写入,5 GB 存储。
- 付费版: 读取 $0.001/百万行,写入 $1.00/百万行,存储 $0.75/GB/月。
D1 常用接口
D1 的 API 设计遵循 Prepare -> Bind -> Execute 的链式调用模式,主要围绕 env.DB 对象进行操作。
核心流程方法
prepare(sql)
- 作用: 所有操作的起点。传入 SQL 字符串,返回一个
PreparedStatement对象。此时 SQL 并未执行,只是被编译/准备好了。
bind(param1, param2, ...)
- 作用: 将变量安全地填充到 SQL 语句的占位符 (
?) 中。 - 安全警告: 永远不要使用字符串拼接(如
"WHERE id=" + id),必须使用bind以防止 SQL 注入。
执行方法
all()
- 场景: 查询多行,获取列表、搜索结果。
- 返回: Promise 解析为
{ results: Array, meta: Object }。results是包含每一行对象的数组。
first(column?)
- 场景: 查询单行,根据 ID 查详情、查总数 (
COUNT)。 - 用法:
first(): 返回第一行对象(无结果返回null)。first("column_name"): 直接返回第一行该列的值(如直接拿到 count 数值)。
run()
- 场景: 写入/修改,
INSERT,UPDATE,DELETE。 - 返回:
{ success: Boolean, meta: Object }。注意:它不返回数据行。 - Meta 信息:
meta.changes(受影响行数),meta.last_row_id(自增 ID)。
高级方法
batch([stmt1, stmt2, ...])
- 作用: 批量执行。将多个
PreparedStatement打包成一个请求。 - 优势: 只有一次网络往返(Round-trip),性能远高于
await循环;提供原子性(伪事务),保证语句按顺序执行或报错。
exec(sql_string)
- 作用: 执行包含多条 SQL 的纯字符串。
- 限制: 不支持参数绑定 (
bind)。 - 场景: 仅用于数据库初始化(Migration)、批量建表。严禁用于处理用户输入。
API 速查表
| 方法 | 属于对象 | 用途 | 返回值特征 | 对应 SQL |
|---|---|---|---|---|
prepare(sql) | env.DB | 编译 SQL | 返回 PreparedStatement | - |
bind(...) | Statement | 填入参数 | 返回 PreparedStatement | - |
all() | Statement | 查列表 | { results: [] } | SELECT |
first() | Statement | 查单行 | Object 或 null | SELECT ... LIMIT 1 |
first('col') | Statement | 查单值 | Value (int/string) | SELECT count(*) |
run() | Statement | 写操作 | { success, meta } | INSERT/UPDATE |
batch([]) | env.DB | 批量打包 | [{result1}, {result2}] | 多条语句 |
exec(str) | env.DB | 跑脚本 | PreparedStatement | 多条语句 (无参) |
KV 键值存储
什么是 KV
Cloudflare Workers KV 是一个全球分布式键值存储系统。可以把它想象成一个存储在云端的、持久化的 Map 或 JSON 对象。
核心特性
- 键值对结构: 只能通过 Key 存取 Value,不支持 SQL。
- 全球低延迟: 写入后数据会同步到全球 300+ 数据中心。用户读取时,直接从最近的节点获取,实现毫秒级读取。
- 最终一致性 (Eventual Consistency): 写入新值后,通常需要 60 秒内才能同步到全球。这意味着刚写入的数据可能不会立即被读取到(写慢读快)。
适用场景与对比
KV 非常适合**“读多写少”**的场景,如缓存、配置管理、Session 存储。
存储产品对比:
| 特性 | KV (Workers KV) | D1 (SQL Database) | R2 (Object Storage) |
|---|---|---|---|
| 数据模型 | 键值对 (Key -> Value) | 关系型表 (Table, Row) | 文件/对象 (File) |
| 查询方式 | 只能根据 Key 查 | SQL 语句 (SELECT *) | 只能根据文件名查 |
| 主要用途 | 极速读取的小数据 | 结构化的业务数据 | 大文件存储 |
| 一致性 | 最终一致 (写慢读快) | 强一致性 (支持事务) | 强一致性 |
| 典型场景 | 缓存、配置、Session | 用户表、订单、元数据 | 图片、视频、备份 |
KV 常用接口
假设你在 wrangler.toml 中绑定了名为 MY_KV 的命名空间,通过 env.MY_KV 调用以下方法。
put(key, value, options)
- 作用:写入
- Key: 字符串(最大 512 字节)。
- Value: String, ReadableStream, ArrayBuffer (最大 25MB)。
- Options:
expiration: 绝对过期时间(Unix 时间戳)。expirationTtl: 相对过期时间(秒),最小 60 秒。metadata: 杀手级功能,允许附带额外的 JSON 对象,无需读取 Value 即可获取。
get(key, options)
作用:读取
核心参数
type: 自动转换数据格式。"text"(默认): 返回字符串。"json": 自动解析为对象。"stream": 返回 ReadableStream,适合直接透传给 Response。缓存参数
cacheTtl: 控制边缘节点缓存时长,减少回源查询。
其他常用方法
getWithMetadata(key): 同时返回{ value, metadata }。delete(key): 删除数据。即使 Key 不存在也会返回成功。list(options): 列出 Key。支持prefix(前缀筛选),limit(数量),cursor(分页)。
R2 对象存储 (Object Storage)
什么是 R2
Cloudflare R2 是对标 Amazon S3 的对象存储服务,主要用于存储图片、视频、PDF 等非结构化大型数据。
核心卖点:零出口流量费
这是 R2 最大的优势。
- 传统云 (AWS/阿里云): 存储要钱,下载/读取(流量)也要钱。流量费往往比存储费贵得多。
- Cloudflare R2: 存储要钱(价格亲民),但取用(下载)完全免费。无论产生了多少 TB 流量,都不收流量费。
对比表:R2 vs D1 vs KV
| 特性 | R2 (Object Storage) | D1 (SQL Database) | KV (Key-Value) |
|---|---|---|---|
| 比喻 | 仓库/文件柜 | Excel 表格 | 便签纸/字典 |
| 存什么 | 大文件 (图片, 视频, ZIP) | 业务数据 (用户, 订单) | 配置, 缓存, Token |
| 大小限制 | 单个文件可达 5 TB | 整个库 10 GB | 单个值最大 25 MB |
| 费用重点 | 存得多就贵,流量免费 | 存得多就贵 | 读得多就贵 |
R2 接口详解
R2 提供两种 API:S3 兼容 API (用于现有工具) 和 Workers 原生 API (用于开发)。在 Workers/Pages 中,我们主要使用原生 API (基于 env.BUCKET 绑定)。
put(key, value, options)
- 作用:上传
- Options:
httpMetadata: 设置 HTTP 头(如contentType)。这很重要,决定了浏览器是预览还是下载文件。customMetadata: 自定义的 Key-Value 数据。
get(key)
- 作用:下载
- 返回值:
R2ObjectBody对象(如果找到)或null。 - 核心属性:
.body: ReadableStream。文件内容流,可以直接传给new Response(obj.body)实现零内存开销下载。.httpMetadata: 之前存入的 Content-Type 等信息。
head(key)
- 作用: 仅查元数据,检查文件是否存在,获取大小或类型,但不下载内容(Body 为空),节省资源。
前端直传
Workers 原生 API 目前不支持生成预签名 URL。如果需要让前端直接上传文件到 R2(不消耗 Worker 资源),你需要引入 S3 SDK (aws4fetch 或 @aws-sdk/client-s3) 来生成 Presigned URL。
开发工具
本章将详细介绍 Cloudflare 官方命令行工具 Wrangler。它是连接开发者本地环境与 Cloudflare 全球边缘网络的桥梁,集成了开发、调试、数据库管理和一键部署等核心功能。
Wrangler 简介
什么是 Wrangler
Wrangler 是 Cloudflare Workers 和 Pages 的官方命令行接口 (CLI)。
如果把 Cloudflare Workers 比作一辆赛车,那么 Wrangler 就是这辆车的方向盘 + 仪表盘 + 维修工具箱。它是你开发、测试、配置和部署 Cloudflare 应用的核心入口。
简单来说:你写的代码想要跑到 Cloudflare 的全球网络上,必须经过 Wrangler。
核心作用
Wrangler 主要解决了开发过程中的三个痛点:
- 本地开发 (Local Development):
- 它在你的电脑上模拟 Cloudflare 的边缘环境。
- 原理: 启动一个基于
workerd运行时(Cloudflare 开发的轻量级服务器),其行为与线上的真实节点几乎完全一致。 - 优势: 你不需要每次修改一行代码就部署到云端去测试。
- 资源绑定 (Bindings Management):
- 它负责将你的代码与 D1 数据库、KV 存储、R2 存储桶连接起来。
- 通过配置文件,它告诉 Worker:“
env.DB这个变量对应的是哪个数据库”。
- 一键部署 (Deployment):
- 将你的代码、配置和环境变量打包,瞬间分发到 Cloudflare 全球 300+ 个城市的数据中心。
工作原理
当你运行 npx wrangler dev 时,后台发生了以下过程:
- Wrangler 读取
wrangler.toml配置文件。 - 启动一个基于 Miniflare 的本地模拟器。
- 将
src/index.js编译并运行在这个服务器中。 - D1 模拟: 如果配置了 D1,它会在本地
.wrangler文件夹下生成一个 SQLite 文件来模拟 D1 数据库,确保本地操作不会污染线上真实数据。
核心命令速查
Wrangler 功能丰富,但在日常开发中,掌握以下 20% 的核心命令即可解决 90% 的问题。
提示: 建议总是使用
npx wrangler <命令>来运行,确保使用的是项目依赖中安装的版本,而不是全局版本。
基础与鉴权
npx wrangler login作用: 弹窗打开浏览器,授权 Wrangler 访问你的 Cloudflare 账号。
场景: 第一次在新电脑上开发,或者 Token 过期时。
npx wrangler whoami作用: 查看当前登录的用户信息,以及关联的 Account ID。
开发与调试
这是开发过程中使用频率最高的命令。
npx wrangler dev(针对纯 Workers 项目)npx wrangler pages dev <目录>(针对 Pages/全栈项目)作用: 启动本地开发服务器,监听文件变化。
核心参数:
--local(默认):在本地模拟所有服务(D1, KV, R2)。读写的是本地临时文件,不影响线上数据。--remote:在本地运行代码,但连接云端的真实资源。如果你想在本地调试时读写线上的 D1 数据库,必须加上这个参数。--compatibility-date=2024-01-01:指定兼容性日期。快捷键: 运行中按
l键,可以在 Local 和 Remote 模式间动态切换。
数据库操作
Wrangler 是操作 D1 数据库的主要入口。
npx wrangler d1 create <数据库名>- 作用: 创建一个新的数据库。
npx wrangler d1 list- 作用: 列出所有数据库及其 ID。
npx wrangler d1 execute <数据库名> --file=./schema.sql- 作用: 执行 SQL 脚本文件。常用于数据库初始化(建表)。
- 关键参数:
--local(默认):在本地开发环境的临时数据库执行。--remote:必须显式加上,才会对云端真实的数据库执行。
npx wrangler d1 execute <数据库名> --command="SELECT * FROM users"- 作用: 执行单条 SQL 语句。常用于快速查数据、Debug。
监控与日志
npx wrangler tail- 作用: 实时监听云端 Worker 的日志流。
- 场景: 类似于 Linux 的
tail -f。当你部署上去后发现报错(如 500 Error),用这个命令可以看到console.log的输出和异常堆栈。 - 技巧: 可以配合 grep 过滤日志,例如
npx wrangler tail | grep "Error"。
部署与发布
npx wrangler deploy(Workers)npx wrangler pages deploy <构建目录>(Pages)- 作用: 将代码和静态资源发布到公网。
- 示例:
npx wrangler pages deploy dist --project-name my-115-tool。
环境变量与敏感信息管理
在开发过程中,如何安全地管理 API Key、Token 或 Cookie 等敏感信息至关重要。
线上环境 (Secrets)
严禁将密码或 Cookie 直接写在代码里提交到 GitHub。对于线上环境,应使用 Cloudflare 的 Secret 存储。
npx wrangler secret put <KEY_NAME>- 作用: 上传一个加密的环境变量到 Cloudflare。
- 交互: 运行后,终端会提示输入具体的值(输入过程不可见)。
- 示例: 设置
COOKIE_115。
npx wrangler secret list- 作用: 列出已设置的密钥名称(出于安全考虑,不会显示具体的值)。
本地开发环境 (.dev.vars)
Wrangler 在本地运行时(wrangler pages dev),不会读取 Cloudflare 后台设置的 Secret,而是读取项目根目录下的 .dev.vars 文件。
操作步骤:
- 在项目根目录创建文件
.dev.vars。 - 填入变量,格式为
KEY=VALUE。
文件示例 (.dev.vars):
COOKIE_115=UID=12345;CID=abcde;SEID=...注意: 确保
.dev.vars文件在.gitignore中,防止意外提交到版本控制系统。
常用工作流总结
针对全栈项目(如 115 网盘工具),推荐的日常工作流命令如下:
- 日常开发:
npx wrangler pages dev . - 修改数据库结构 (本地测试):
npx wrangler d1 execute my-db --local --file=./schema.sql - 修改数据库结构 (应用到线上):
npx wrangler d1 execute my-db --remote --file=./schema.sql - 发布上线:
npm run build && npx wrangler pages deploy dist
实战:115 网盘本地化工具
本章将整合前几章学习的 Pages (前端托管)、Functions (后端逻辑) 和 Wrangler (本地开发) 知识,构建一个完整的全栈应用——“115 网盘本地化管理工具”。
这个项目的核心痛点是:115 网盘的 API 有严格的 Cookie 校验和防盗链机制,前端无法直接在浏览器中调用(会报跨域 CORS 错误)。我们需要利用 Cloudflare Pages Functions 作为“中间人”来转发请求。
115 网盘实战架构
核心逻辑
该项目的架构设计如下:
- 前端 (Vue 3): 负责界面交互(如展示文件列表、重命名按钮、删除按钮)。
- 后端 (Pages Functions): 运行在 Cloudflare 边缘,负责中转请求。它会读取环境变量中的 Cookie,伪造请求头欺骗 115 服务器,并将结果返回给前端。
- 本地环境: 使用 Wrangler 模拟 Cloudflare 生产环境,代理 Vite 服务器。
项目初始化与结构
首先创建一个标准的 Vue 项目,然后在根目录下建立 Cloudflare Pages 特有的目录结构。
my-115-project/
├── .dev.vars # 本地敏感变量 (存放 Cookie)
├── package.json # 项目依赖与脚本
├── wrangler.toml # 资源绑定配置
├── src/ # Vue 前端代码
│ └── App.vue
└── functions/ # 后端 API 代码 (约定路由)
└── api/
├── 115.js # -> 映射为 /api/115 接口
└── img-proxy.js # -> 映射为 /api/img-proxy 接口接口与鉴权 (通用中转)
我们需要编写一个通用的 API 接口,用于接收前端传来的目标 URL,并附带上 Cookie 转发给 115。
后端代码实现
请在 functions/api/115.js 中写入以下代码:
export async function onRequest(context) {
// 1. 从环境变量中获取 Cookie
// 在本地,它读取 .dev.vars;在线上,它读取 Cloudflare 后台配置的 Secrets
const COOKIE = context.env.COOKIE_115
if (!COOKIE) {
return new Response(JSON.stringify({ state: false, error: '未配置 Cookie' }), {
headers: { 'Content-Type': 'application/json' }
})
}
// 2. 获取前端传来的参数 (Target URL)
const url = new URL(context.request.url)
const targetUrl = url.searchParams.get('url') // 例如 ?url=https://webapi.115.com/...
if (!targetUrl) {
return new Response('Missing url param', { status: 400 })
}
// 3. 发起请求给 115 (Server-to-Server)
// 注意:这里伪造了 User-Agent 和 Cookie,绕过 115 的校验
const resp = await fetch(targetUrl, {
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
Cookie: COOKIE
}
})
// 4. 把 115 的返回结果直接透传给前端
const data = await resp.json()
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' }
})
}API 深度解析
onRequest(context): 这是 Pages Functions 的标准入口函数。context.env: 这是一个包含所有环境变量的对象。- 本地开发时:它加载
.dev.vars文件中的内容。 - 线上部署时:它加载 Cloudflare Dashboard 中设置的 Environment Variables (Secrets)。
- 本地开发时:它加载
context.request: 一个标准的 Web APIRequest对象,包含了前端发来的所有信息(URL、Method、Headers)。
敏感信息管理 (Cookie)
严禁将 Cookie 硬编码在代码中提交到 GitHub。
- 线上环境: 使用 Wrangler 命令上传加密存储:
npx wrangler secret put COOKIE_115
# 终端会提示你输入具体的值,输入过程不可见- 本地环境: 详见 5.4 节。
图片代理服务 (防盗链处理)
115 的图片服务器有防盗链检查,如果请求头中的 Referer 不是 115.com,图片将无法加载(显示 403 Forbidden)。我们需要一个代理来“清洗”请求头。
后端代码实现
请在 functions/api/img-proxy.js 中写入以下代码:
export async function onRequest(context) {
const COOKIE = context.env.COOKIE_115
const url = new URL(context.request.url)
const targetUrl = url.searchParams.get('url')
if (!targetUrl) return new Response('Missing URL', { status: 400 })
// 发起请求,核心在于伪造 Referer
const resp = await fetch(targetUrl, {
headers: {
Cookie: COOKIE,
Referer: 'https://115.com/' // 关键:骗过防盗链检查
}
})
// 直接返回图片流 (Stream),实现零内存开销
// 不要使用 await resp.blob(),那会消耗大量内存
return new Response(resp.body, {
headers: {
// 转发原始图片的 Content-Type (如 image/jpeg)
'Content-Type': resp.headers.get('Content-Type') || 'image/jpeg'
}
})
}前端调用示例
在 Vue 组件中,你不能直接写 <img src="https://115.com/img/..." />。 你需要写:
<img src="/api/img-proxy?url=https://115.com/img/..." />这样请求会先发给你的 Worker,Worker 加上 Referer: https://115.com/ 后再去请求 115,从而成功拿到图片。
本地全栈开发环境
为了在本地同时运行 Vue 前端和 Functions 后端,并让它们能够通信,我们需要配置 Wrangler 代理。
配置本地环境变量
Wrangler 在本地运行时不会去读取线上的 Secrets。你必须在项目根目录创建一个 .dev.vars 文件。
文件内容 (.dev.vars):
COOKIE_115=UID=12345;CID=abcde;SEID=...注意: 等号周围不要有空格。此文件包含敏感信息,请务必加入
.gitignore。
修改启动脚本
普通的 npm run dev 只能启动 Vue,无法运行 functions/ 目录下的后端代码。我们需要修改 package.json 的 scripts 字段。
修改前:
"scripts": {
"dev": "vite",
"build": "vite build"
}修改后:
"scripts": {
"dev": "vite",
"build": "vite build",
"pages:dev": "wrangler pages dev -- proxy 5173"
}运行与调试
在终端运行以下命令启动开发环境:
npm run pages:dev运行原理解析:
启动 Wrangler: 命令会启动 Wrangler 的本地服务器(通常在
http://localhost:8788)。启动 Vite: Wrangler 会自动运行
npm run dev(启动 Vite 服务器,端口 5173)。请求代理 (Proxy):
当你访问
http://localhost:8788/api/115时 -> Wrangler 拦截请求 -> 执行functions/api/115.js-> 返回结果。当你访问
http://localhost:8788/assets/logo.png时 -> Wrangler 发现这不是 API -> 将请求转发给 Vite (端口 5173) -> 返回静态资源。
重要提示: 在浏览器中开发时,请务必访问
http://localhost:8788,而不是 Vite 的 5173 端口,否则你的 API 请求会失败(404 或跨域)。